/**
 * 移动端工具函数
 */

// 移动端设备检测
export const isMobileDevice = (): boolean => {
  const userAgent = navigator.userAgent.toLowerCase()
  const mobileKeywords = [
    'mobile',
    'android',
    'iphone',
    'ipad',
    'ipod',
    'blackberry',
    'iemobile',
    'opera mini'
  ]
  return mobileKeywords.some((keyword) => userAgent.includes(keyword))
}

// 检测是否为触摸设备
export const isTouchDevice = (): boolean => {
  return 'ontouchstart' in window || navigator.maxTouchPoints > 0
}

// 获取视口宽度
export const getViewportWidth = (): number => {
  return window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth
}

// 获取视口高度
export const getViewportHeight = (): number => {
  return window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight
}

// 检测是否为移动端屏幕尺寸
export const isMobileScreen = (breakpoint: number = 768): boolean => {
  return getViewportWidth() <= breakpoint
}

// 检测是否为平板屏幕尺寸
export const isTabletScreen = (
  minBreakpoint: number = 768,
  maxBreakpoint: number = 1024
): boolean => {
  const width = getViewportWidth()
  return width > minBreakpoint && width <= maxBreakpoint
}

// 检测是否为桌面屏幕尺寸
export const isDesktopScreen = (breakpoint: number = 1024): boolean => {
  return getViewportWidth() > breakpoint
}

// 防抖函数
export const debounce = <T extends (...args: any[]) => void>(
  func: T,
  wait: number,
  immediate: boolean = false
): ((...args: Parameters<T>) => void) => {
  let timeout: NodeJS.Timeout | null = null
  return function executedFunction(...args: Parameters<T>) {
    const later = () => {
      timeout = null
      if (!immediate) func(...args)
    }
    const callNow = immediate && !timeout
    if (timeout) clearTimeout(timeout)
    timeout = setTimeout(later, wait)
    if (callNow) func(...args)
  }
}

// 节流函数
export const throttle = <T extends (...args: any[]) => void>(
  func: T,
  limit: number
): ((...args: Parameters<T>) => void) => {
  let inThrottle: boolean = false
  return function executedFunction(...args: Parameters<T>) {
    if (!inThrottle) {
      func(...args)
      inThrottle = true
      setTimeout(() => (inThrottle = false), limit)
    }
  }
}

// 响应式监听器
export const createResponsiveListener = (
  callback: (isMobile: boolean) => void,
  breakpoint: number = 768
): (() => void) => {
  const checkResponsive = () => {
    callback(isMobileScreen(breakpoint))
  }

  const debouncedCheck = debounce(checkResponsive, 100)

  // 初始检查
  checkResponsive()

  // 监听窗口大小变化
  window.addEventListener('resize', debouncedCheck)

  // 返回清理函数
  return () => {
    window.removeEventListener('resize', debouncedCheck)
  }
}

// 获取元素的响应式类名
export const getResponsiveClass = (baseClass: string, breakpoint: number = 768): string => {
  const suffix = isMobileScreen(breakpoint) ? '-mobile' : '-desktop'
  return `${baseClass}${suffix}`
}

// 动态设置元素样式
export const setResponsiveStyle = (
  element: HTMLElement,
  mobileStyles: Partial<CSSStyleDeclaration>,
  desktopStyles: Partial<CSSStyleDeclaration>,
  breakpoint: number = 768
): void => {
  const styles = isMobileScreen(breakpoint) ? mobileStyles : desktopStyles
  Object.assign(element.style, styles)
}

// 移动端友好的滚动到顶部
export const scrollToTop = (smooth: boolean = true): void => {
  if (smooth) {
    window.scrollTo({
      top: 0,
      behavior: 'smooth'
    })
  } else {
    window.scrollTo(0, 0)
  }
}

// 移动端友好的滚动到元素
export const scrollToElement = (
  element: HTMLElement | string,
  offset: number = 0,
  smooth: boolean = true
): void => {
  const targetElement =
    typeof element === 'string' ? (document.querySelector(element) as HTMLElement) : element

  if (!targetElement) return

  const elementTop = targetElement.offsetTop - offset

  if (smooth) {
    window.scrollTo({
      top: elementTop,
      behavior: 'smooth'
    })
  } else {
    window.scrollTo(0, elementTop)
  }
}

// 禁用/启用页面滚动（移动端弹窗时有用）
export const toggleBodyScroll = (disable: boolean): void => {
  if (disable) {
    document.body.style.overflow = 'hidden'
    document.body.style.position = 'fixed'
    document.body.style.width = '100%'
  } else {
    document.body.style.overflow = ''
    document.body.style.position = ''
    document.body.style.width = ''
  }
}

// 获取安全区域信息（适用于有刘海屏的设备）
export const getSafeAreaInsets = (): {
  top: number
  right: number
  bottom: number
  left: number
} => {
  const computedStyle = getComputedStyle(document.documentElement)

  return {
    top: parseInt(computedStyle.getPropertyValue('--safe-area-inset-top') || '0'),
    right: parseInt(computedStyle.getPropertyValue('--safe-area-inset-right') || '0'),
    bottom: parseInt(computedStyle.getPropertyValue('--safe-area-inset-bottom') || '0'),
    left: parseInt(computedStyle.getPropertyValue('--safe-area-inset-left') || '0')
  }
}

// 移动端振动反馈
export const vibrate = (pattern: number | number[] = 100): void => {
  if ('vibrate' in navigator) {
    navigator.vibrate(pattern)
  }
}

// 检测网络状态
export const getNetworkStatus = (): {
  online: boolean
  effectiveType?: string
  downlink?: number
  rtt?: number
} => {
  const connection =
    (navigator as any).connection ||
    (navigator as any).mozConnection ||
    (navigator as any).webkitConnection

  return {
    online: navigator.onLine,
    effectiveType: connection?.effectiveType,
    downlink: connection?.downlink,
    rtt: connection?.rtt
  }
}

// 移动端手势识别基础类
export class MobileGestureRecognizer {
  private startX: number = 0
  private startY: number = 0
  private endX: number = 0
  private endY: number = 0
  private minSwipeDistance: number = 50

  constructor(
    private element: HTMLElement,
    private callbacks: {
      onSwipeLeft?: () => void
      onSwipeRight?: () => void
      onSwipeUp?: () => void
      onSwipeDown?: () => void
      onTap?: () => void
    },
    minSwipeDistance: number = 50
  ) {
    this.minSwipeDistance = minSwipeDistance
    this.init()
  }

  private init(): void {
    this.element.addEventListener('touchstart', this.handleTouchStart.bind(this), { passive: true })
    this.element.addEventListener('touchend', this.handleTouchEnd.bind(this), { passive: true })
  }

  private handleTouchStart(e: TouchEvent): void {
    const touch = e.touches[0]
    this.startX = touch.clientX
    this.startY = touch.clientY
  }

  private handleTouchEnd(e: TouchEvent): void {
    const touch = e.changedTouches[0]
    this.endX = touch.clientX
    this.endY = touch.clientY

    this.detectGesture()
  }

  private detectGesture(): void {
    const deltaX = this.endX - this.startX
    const deltaY = this.endY - this.startY

    const absDeltaX = Math.abs(deltaX)
    const absDeltaY = Math.abs(deltaY)

    // 如果移动距离太小，认为是点击
    if (absDeltaX < this.minSwipeDistance && absDeltaY < this.minSwipeDistance) {
      this.callbacks.onTap?.()
      return
    }

    // 判断是水平滑动还是垂直滑动
    if (absDeltaX > absDeltaY) {
      // 水平滑动
      if (deltaX > 0) {
        this.callbacks.onSwipeRight?.()
      } else {
        this.callbacks.onSwipeLeft?.()
      }
    } else {
      // 垂直滑动
      if (deltaY > 0) {
        this.callbacks.onSwipeDown?.()
      } else {
        this.callbacks.onSwipeUp?.()
      }
    }
  }

  public destroy(): void {
    this.element.removeEventListener('touchstart', this.handleTouchStart.bind(this))
    this.element.removeEventListener('touchend', this.handleTouchEnd.bind(this))
  }
}
